<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Node 第 7 天 | Megasu的笔记</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/heima2020/favicon.ico">
    <meta name="description" content="Megasu的笔记整理">
    <meta name="author" content="Megasu">
    <meta name="Keywords" content="学习网站,前端,分享">
    <link rel="preload" href="/heima2020/assets/css/0.styles.aa663799.css" as="style"><link rel="preload" href="/heima2020/assets/js/app.e2adc9d2.js" as="script"><link rel="preload" href="/heima2020/assets/js/2.7389c9d3.js" as="script"><link rel="preload" href="/heima2020/assets/js/40.a6ba2743.js" as="script"><link rel="prefetch" href="/heima2020/assets/js/10.8b750e5f.js"><link rel="prefetch" href="/heima2020/assets/js/11.9224f975.js"><link rel="prefetch" href="/heima2020/assets/js/12.3ea117b6.js"><link rel="prefetch" href="/heima2020/assets/js/13.7524b74f.js"><link rel="prefetch" href="/heima2020/assets/js/14.cee0fcf8.js"><link rel="prefetch" href="/heima2020/assets/js/15.7a4a27f7.js"><link rel="prefetch" href="/heima2020/assets/js/16.947d882b.js"><link rel="prefetch" href="/heima2020/assets/js/17.79d3becb.js"><link rel="prefetch" href="/heima2020/assets/js/18.48208e3a.js"><link rel="prefetch" href="/heima2020/assets/js/19.3d0c49ef.js"><link rel="prefetch" href="/heima2020/assets/js/20.1f6114c8.js"><link rel="prefetch" href="/heima2020/assets/js/21.85e67b4a.js"><link rel="prefetch" href="/heima2020/assets/js/22.ce482f4d.js"><link rel="prefetch" href="/heima2020/assets/js/23.a150bd35.js"><link rel="prefetch" href="/heima2020/assets/js/24.8cd80d5d.js"><link rel="prefetch" href="/heima2020/assets/js/25.0001c7c1.js"><link rel="prefetch" href="/heima2020/assets/js/26.aa4d65a5.js"><link rel="prefetch" href="/heima2020/assets/js/27.baffff1d.js"><link rel="prefetch" href="/heima2020/assets/js/28.20430dcf.js"><link rel="prefetch" href="/heima2020/assets/js/29.7bbc3c04.js"><link rel="prefetch" href="/heima2020/assets/js/3.0076a912.js"><link rel="prefetch" href="/heima2020/assets/js/30.5f74696f.js"><link rel="prefetch" href="/heima2020/assets/js/31.a0bf56d6.js"><link rel="prefetch" href="/heima2020/assets/js/32.dd5a93dd.js"><link rel="prefetch" href="/heima2020/assets/js/33.92de7335.js"><link rel="prefetch" href="/heima2020/assets/js/34.bf468ed6.js"><link rel="prefetch" href="/heima2020/assets/js/35.28502be1.js"><link rel="prefetch" href="/heima2020/assets/js/36.3622a14c.js"><link rel="prefetch" href="/heima2020/assets/js/37.626e17d3.js"><link rel="prefetch" href="/heima2020/assets/js/38.860020b8.js"><link rel="prefetch" href="/heima2020/assets/js/39.c092c283.js"><link rel="prefetch" href="/heima2020/assets/js/4.586af112.js"><link rel="prefetch" href="/heima2020/assets/js/41.43d70bcd.js"><link rel="prefetch" href="/heima2020/assets/js/42.6486a709.js"><link rel="prefetch" href="/heima2020/assets/js/43.670b256a.js"><link rel="prefetch" href="/heima2020/assets/js/44.eb371480.js"><link rel="prefetch" href="/heima2020/assets/js/45.5b45f11e.js"><link rel="prefetch" href="/heima2020/assets/js/46.bc59be94.js"><link rel="prefetch" href="/heima2020/assets/js/47.ec36fca9.js"><link rel="prefetch" href="/heima2020/assets/js/48.51e80f8f.js"><link rel="prefetch" href="/heima2020/assets/js/5.6eb7e243.js"><link rel="prefetch" href="/heima2020/assets/js/6.1b7d5a6d.js"><link rel="prefetch" href="/heima2020/assets/js/7.f611fe3c.js"><link rel="prefetch" href="/heima2020/assets/js/8.c14cc922.js"><link rel="prefetch" href="/heima2020/assets/js/9.cd5538bb.js">
    <link rel="stylesheet" href="/heima2020/assets/css/0.styles.aa663799.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/heima2020/" class="home-link router-link-active"><!----> <span class="site-name">Megasu的笔记</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><a href="/heima2020/node/day01" class="sidebar-heading clickable open"><span>Node</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/heima2020/node/day01.html" class="sidebar-link">Node 第 1 天</a></li><li><a href="/heima2020/node/day02.html" class="sidebar-link">Node 第 2 天</a></li><li><a href="/heima2020/node/day03.html" class="sidebar-link">Node 第 3 天</a></li><li><a href="/heima2020/node/day04.html" class="sidebar-link">Node 第 4 天</a></li><li><a href="/heima2020/node/day05.html" class="sidebar-link">Node 第 5 天</a></li><li><a href="/heima2020/node/day06.html" class="sidebar-link">Node 第 6 天</a></li><li><a href="/heima2020/node/day07.html" aria-current="page" class="active sidebar-link">Node 第 7 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#node-第-7-天" class="sidebar-link">Node 第 7 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_1-学习目标" class="sidebar-link">1.  学习目标</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_2-登录功能" class="sidebar-link">2. 登录功能</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_3-获取用户的基本信息" class="sidebar-link">3. 获取用户的基本信息</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_4-更新用户的基本信息" class="sidebar-link">4. 更新用户的基本信息</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_5-重置密码" class="sidebar-link">5. 重置密码</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day07.html#_6-更换头像" class="sidebar-link">6.  更换头像</a></li></ul></li></ul></li><li><a href="/heima2020/node/day08.html" class="sidebar-link">Node 第 8 天</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="node-第-7-天"><a href="#node-第-7-天" class="header-anchor">#</a> Node 第 7 天</h2> <h3 id="_1-学习目标"><a href="#_1-学习目标" class="header-anchor">#</a> 1.  学习目标</h3> <p>◆ 完成登录功能的开发</p> <p>◆ 能够获取用户的信息并重置密码和头像</p> <h3 id="_2-登录功能"><a href="#_2-登录功能" class="header-anchor">#</a> 2. 登录功能</h3> <h4 id="_2-1-实现步骤"><a href="#_2-1-实现步骤" class="header-anchor">#</a> 2.1 实现步骤</h4> <ol><li>检测表单数据是否合法</li> <li>根据用户名查询用户的数据</li> <li>判断用户输入的密码是否正确</li> <li>生成 <code>JWT</code> 的 <code>Token</code> 字符串</li></ol> <h4 id="_2-2-检测表单数据是否合法"><a href="#_2-2-检测表单数据是否合法" class="header-anchor">#</a> 2.2 检测表单数据是否合法</h4> <ol><li>将  <code>/router/user.js</code> 中  登录 的路由代码修改进行修改</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 注册新用户</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/reguser'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>reg_login_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>regUser<span class="token punctuation">)</span>

<span class="token comment">// 登录功能</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>reg_login_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userHandle<span class="token punctuation">.</span>login<span class="token punctuation">)</span>
</code></pre></div><h4 id="_2-3-根据用户名查询用户的数据"><a href="#_2-3-根据用户名查询用户的数据" class="header-anchor">#</a> 2.3 根据用户名查询用户的数据</h4> <ol><li>接收表单的数据</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 接收表单传递过来的数据</span>
<span class="token keyword">const</span> userInfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
</code></pre></div><ol start="2"><li>定义 <code>sql</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 定义 sql 语句</span>
<span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
</code></pre></div><ol start="3"><li>执行 <code>sql</code> 语句，查询用户的数据</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 执行 sql 语句，根据用户名查询用户的信息</span>
db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userInfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 指定 sql 失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
  <span class="token comment">// 执行 sql 语句成功，但是获取到的数据条数不等于 1</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败'</span><span class="token punctuation">)</span>
  <span class="token comment">// 判断用户名和密码是否正确</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'login Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="4"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 登录的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 接收表单传递过来的数据</span>
  <span class="token keyword">const</span> userInfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
  <span class="token comment">// 执行 sql 语句，根据用户名查询用户的信息</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userInfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 指定 sql 失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    <span class="token comment">// 执行 sql 语句成功，但是获取到的数据条数不等于 1</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败'</span><span class="token punctuation">)</span>
    <span class="token comment">// 判断用户名和密码是否正确</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'login Ok'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_2-4-判断用户输入的密码是否正确"><a href="#_2-4-判断用户输入的密码是否正确" class="header-anchor">#</a> 2.4 判断用户输入的密码是否正确</h4> <blockquote><p>核心实现思路：调用  <code>bcrypt.compareSync(用户提交的密码, 数据库中的密码)</code> 方法比较密码是否一致，</p> <p>返回值是布尔值（true 一致、false 不一致）</p></blockquote> <ol><li>实现代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 判断用户名和密码是否正确</span>
<span class="token comment">// 将用户输入的密码和数据库中存储的密码进行比较</span>
<span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
<span class="token comment">// 根据对比后的结果进行判断</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败！'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li><p>完整代码</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 登录的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 接收表单传递过来的数据</span>
  <span class="token keyword">const</span> userInfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
  <span class="token comment">// 执行 sql 语句，根据用户名查询用户的信息</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userInfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 指定 sql 失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    <span class="token comment">// 执行 sql 语句成功，但是获取到的数据条数不等于 1</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败'</span><span class="token punctuation">)</span>

    <span class="token comment">// 判断用户名和密码是否正确</span>
    <span class="token comment">// 将用户输入的密码和数据库中存储的密码进行比较</span>
    <span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
    <span class="token comment">// 根据对比后的结果进行判断</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败！'</span><span class="token punctuation">)</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'login Ok'</span><span class="token punctuation">)</span>
    
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div></li></ol> <h4 id="_2-5-分析生成-token-字符串的步骤"><a href="#_2-5-分析生成-token-字符串的步骤" class="header-anchor">#</a> 2.5 分析生成 <code>Token</code> 字符串的步骤</h4> <ol><li>通过 <code>ES6</code> 的高级语法，快速剔除  <code>密码</code> 和  <code>头像</code> 的值</li> <li>运行如下的命令，安装生成 <code>Token</code> 字符串的包</li> <li>在  <code>/router_handler/user.js</code> 模块的头部区域，导入  <code>jsonwebtoken</code> 包</li> <li>创建  <code>config.js</code> 文件，并向外共享 加密 和 还原 <code>Token</code> 的  <code>jwtSecretKey</code> 字符串</li> <li>将用户信息对象加密成 <code>Token</code> 字符串</li> <li>将生成的 <code>Token</code> 字符串响应给客户端</li></ol> <h4 id="_2-6-生成-jwt-的-token-步骤"><a href="#_2-6-生成-jwt-的-token-步骤" class="header-anchor">#</a> 2.6 生成 <code>JWT</code> 的 <code>Token</code> 步骤</h4> <ol><li>通过 <code>ES6</code> 的高级语法，快速剔除  <code>密码</code> 和  <code>头像</code> 的值</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 登录成功以后，给用户返回 token 值</span>
<span class="token comment">// 剔除 user 返回的 头像和密码 信息，</span>
<span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> password<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span> user_pic<span class="token operator">:</span> <span class="token string">''</span> <span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>运行如下的命令，安装生成 <code>Token</code> 字符串的包</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i jsonwebtoken@<span class="token number">8.5</span><span class="token number">.1</span> <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div><ol start="3"><li>在  <code>/router_handler/user.js</code> 模块的头部区域，导入  <code>jsonwebtoken</code> 包</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 生成 Token 字符串</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="4"><li>创建  <code>config.js</code> 文件，并向外共享 加密 和 还原 <code>Token</code> 的  <code>jwtSecretKey</code> 字符串</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 全局配置文件</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// 加密和解密的 Token 密钥</span>
  jwtSecretKey<span class="token operator">:</span> <span class="token string">'itheima No1. ^_^'</span><span class="token punctuation">,</span>
  expiresIn<span class="token operator">:</span> <span class="token string">'10h'</span> <span class="token comment">// 设置 token 有效期为 10 小时</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="5"><li>将用户信息对象加密成 <code>Token</code> 字符串</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入配置文件</span>
<span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../config'</span><span class="token punctuation">)</span>
</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 生成 Token 字符串内容</span>
<span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> config<span class="token punctuation">.</span>jwtSecretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span>expiresIn<span class="token operator">:</span> config<span class="token punctuation">.</span>expiresIn<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><ol start="6"><li>将生成的 <code>Token</code> 字符串响应给客户端</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 将生成的 Token 字符串响应给客户端</span>
res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
  message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
  <span class="token comment">// 为了方便客户端使用 Token，在服务器端直接拼接上 Bearer 的前缀</span>
  token<span class="token operator">:</span> <span class="token string">'Bearer '</span> <span class="token operator">+</span> tokenStr<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="7"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
 * 定义和用户相关的路由处理函数，功 /router/user.js 模块尽心调用
 */</span>

<span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> bcrypt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcryptjs'</span><span class="token punctuation">)</span>
<span class="token comment">// 生成 Token 字符串</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token comment">// 导入配置文件</span>
<span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../config'</span><span class="token punctuation">)</span>

<span class="token comment">// 注册用户的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">regUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token comment">// 登录的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 接收表单传递过来的数据</span>
  <span class="token keyword">const</span> userInfo <span class="token operator">=</span> req<span class="token punctuation">.</span>body
  <span class="token comment">// 定义 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where username=?</span><span class="token template-punctuation string">`</span></span>
  <span class="token comment">// 执行 sql 语句，根据用户名查询用户的信息</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> userInfo<span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 指定 sql 失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    <span class="token comment">// 执行 sql 语句成功，但是获取到的数据条数不等于 1</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败'</span><span class="token punctuation">)</span>

    <span class="token comment">// 判断用户名和密码是否正确</span>
    <span class="token comment">// 将用户输入的密码和数据库中存储的密码进行比较</span>
    <span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
    <span class="token comment">// 根据对比后的结果进行判断</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'登录失败！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 登录成功以后，给用户返回 token 值</span>
    <span class="token comment">// 剔除 user 返回的 头像和密码 信息，</span>
    <span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> password<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span> user_pic<span class="token operator">:</span> <span class="token string">''</span> <span class="token punctuation">}</span>

    <span class="token comment">// 生成 Token 字符串内容</span>
    <span class="token keyword">const</span> tokenStr <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> config<span class="token punctuation">.</span>jwtSecretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span>expiresIn<span class="token operator">:</span> config<span class="token punctuation">.</span>expiresIn<span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token comment">// 将生成的 Token 字符串响应给客户端</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'登录成功！'</span><span class="token punctuation">,</span>
      <span class="token comment">// 为了方便客户端使用 Token，在服务器端直接拼接上 Bearer 的前缀</span>
      token<span class="token operator">:</span> <span class="token string">'Bearer '</span> <span class="token operator">+</span> tokenStr<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_2-7-配置解析-token-的中间件"><a href="#_2-7-配置解析-token-的中间件" class="header-anchor">#</a> 2.7 配置解析 <code>Token</code> 的中间件</h4> <ol><li>运行如下的命令，安装解析 <code>Token</code> 的中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>cnpm i express<span class="token operator">-</span>jwt@<span class="token number">5.3</span><span class="token number">.3</span> <span class="token operator">-</span><span class="token constant">S</span>
</code></pre></div><ol start="2"><li>在  <code>app.js</code> 中注册路由之前，配置解析 <code>Token</code> 的中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入全局的配置文件</span>
<span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./config'</span><span class="token punctuation">)</span>
<span class="token comment">// 解析 token 的中间件</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>
<span class="token comment">// 使用 .unless 方法指定哪些接口不需要进行 Token 的身份认证</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">expressJWT</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> config<span class="token punctuation">.</span>jwtSecretKey <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unless</span><span class="token punctuation">(</span><span class="token punctuation">{</span> path<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token regex">/^\/api\//</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 导入并注册用户路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router/user'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> userRouter<span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>在  <code>app.js</code> 中的  错误级别中间件 里面，捕获并处理 <code>Token</code> 认证失败后的错误</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 错误中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 数据验证失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err <span class="token keyword">instanceof</span> <span class="token class-name">joi<span class="token punctuation">.</span>ValidationError</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
    
  <span class="token comment">// 在身份认证失败后，捕获并处理 Token 认证失败后的错误</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">.</span>name <span class="token operator">===</span> <span class="token string">'UnauthorizedError'</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'身份认证失败！'</span><span class="token punctuation">)</span>
    
  <span class="token comment">// 未知错误</span>
  res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="_3-获取用户的基本信息"><a href="#_3-获取用户的基本信息" class="header-anchor">#</a> 3. 获取用户的基本信息</h3> <h4 id="_3-1-实现步骤"><a href="#_3-1-实现步骤" class="header-anchor">#</a> 3.1 实现步骤</h4> <ol><li>初始化 路由 模块</li> <li>初始化 路由处理函数 模块</li> <li>获取用户的基本信息</li></ol> <h4 id="_3-2-初始化路由模块"><a href="#_3-2-初始化路由模块" class="header-anchor">#</a> 3.2 初始化路由模块</h4> <ol><li>创建  <code>/router/userinfo.js</code> 路由模块，并初始化如下的代码结构</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> route <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./user'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 向外共享路由对象</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><ol start="2"><li>在  <code>app.js</code> 中导入并使用个人中心的路由模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入并注册用户路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router/user'</span><span class="token punctuation">)</span>
<span class="token comment">// 导入并使用用户信息的路由模块</span>
<span class="token keyword">const</span> userinfoRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router/userinfo'</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> userRouter<span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/my'</span><span class="token punctuation">,</span> userinfoRouter<span class="token punctuation">)</span>
</code></pre></div><h4 id="_3-3-初始化-路由处理函数-模块"><a href="#_3-3-初始化-路由处理函数-模块" class="header-anchor">#</a> 3.3 初始化 路由处理函数 模块</h4> <ol><li>创建  <code>/router_handler/userinfo.js</code> 路由处理函数模块，并初始化如下的代码结构</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 创建用户基本信息的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">getUserInfo</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="2"><li>修改  <code>/router/userinfo.js</code>  中的代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> route <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./user'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 导入用户信息的处理函数模块</span>
<span class="token keyword">const</span> userinfo_handler <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../router_handler/userinfo'</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>getUserInfo<span class="token punctuation">)</span>

<span class="token comment">// 向外共享路由对象</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><h4 id="_3-4-获取用户的基本信息"><a href="#_3-4-获取用户的基本信息" class="header-anchor">#</a> 3.4 获取用户的基本信息</h4> <ol><li>在  <code>/router_handler/userinfo.js</code> 头部导入数据库操作模块</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>定义 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 定义查询用户信息的 sql 语句</span>
<span class="token keyword">const</span> sql <span class="token operator">=</span> `select id<span class="token punctuation">,</span> username<span class="token punctuation">,</span> nickname<span class="token punctuation">,</span> email<span class="token punctuation">,</span> user_pic <span class="token keyword">from</span> ev_users where id<span class="token operator">=</span><span class="token operator">?</span>
</code></pre></div><ol start="3"><li>调用  <code>db.query()</code> 执行 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 调用 db.query() 执行 sql 语句</span>
db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 执行 sql 语句失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

  <span class="token comment">// 执行的 sql 语句成功，但是查询的结果可能为空</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'获取用户信息失败！'</span><span class="token punctuation">)</span>

  <span class="token comment">// 用户信息获取成功</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    message<span class="token operator">:</span> <span class="token string">'获取用户基本信息成功！'</span><span class="token punctuation">,</span>
    data<span class="token operator">:</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="4"><li>完成代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入数据库操作模块</span>
<span class="token keyword">const</span> db <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../db/index'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建用户基本信息的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">getUserInfo</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义查询用户信息的 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select id, username, nickname, email, user_pic from ev_users where id=?</span><span class="token template-punctuation string">`</span></span>

  <span class="token comment">// 调用 db.query() 执行 sql 语句</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// 执行的 sql 语句成功，但是查询的结果可能为空</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'获取用户信息失败！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 用户信息获取成功</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
      message<span class="token operator">:</span> <span class="token string">'获取用户基本信息成功！'</span><span class="token punctuation">,</span>
      data<span class="token operator">:</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h3 id="_4-更新用户的基本信息"><a href="#_4-更新用户的基本信息" class="header-anchor">#</a> 4. 更新用户的基本信息</h3> <h4 id="_4-1-实现步骤"><a href="#_4-1-实现步骤" class="header-anchor">#</a> 4.1 实现步骤</h4> <ol><li>定义路由和处理函数</li> <li>验证表单数据</li> <li>实现更新用户基本信息的功能</li></ol> <h4 id="_4-2-定义路由和处理函数"><a href="#_4-2-定义路由和处理函数" class="header-anchor">#</a> 4.2 定义路由和处理函数</h4> <ol><li>在  <code>/router/userinfo.js</code> 模块中，新增  更新用户基本信息 的路由</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updateUserInfo<span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>在  <code>/router_handler/userinfo.js</code> 模块中，定义并向外共享  更新用户基本信息 的路由处理函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户基本信息的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updateUserInfo</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_4-3-定义验证规则对象"><a href="#_4-3-定义验证规则对象" class="header-anchor">#</a> 4.3 定义验证规则对象</h4> <ol><li>在  <code>/schema/user.js</code> 验证规则模块中，定义  <code>id</code> ， <code>nickname</code> ， <code>email</code> 的验证规则</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 定义 id, nickname, emial 的验证规则</span>
<span class="token keyword">const</span> id <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">number</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">integer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> nickname <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> email <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">email</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>并使用 <code>exports</code> 向外共享如下的  验证规则对象</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户基本信息的验证规则对象</span>
exports<span class="token punctuation">.</span>update_userinfo_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    id<span class="token punctuation">,</span>
    nickname<span class="token punctuation">,</span>
    email<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="3"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// /schema/user.js</span>

<span class="token keyword">const</span> joi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@hapi/joi'</span><span class="token punctuation">)</span>

<span class="token comment">// 验证用户名、密码的规则</span>
<span class="token keyword">const</span> username <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">alphanum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> password <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pattern</span><span class="token punctuation">(</span><span class="token regex">/^[\S]{6,12}$/</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义 id, nickname, emial 的验证规则</span>
<span class="token keyword">const</span> id <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">number</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">integer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> nickname <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> email <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">email</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 登录和注册表单的验证规则对象</span>
exports<span class="token punctuation">.</span>reg_login_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token comment">// 表示需要对 req.body 中的数据进行验证</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    username<span class="token punctuation">,</span>
    password<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">// 更新用户基本信息的验证规则对象</span>
exports<span class="token punctuation">.</span>update_userinfo_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    id<span class="token punctuation">,</span>
    nickname<span class="token punctuation">,</span>
    email<span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_4-4-验证数据规则的合法性"><a href="#_4-4-验证数据规则的合法性" class="header-anchor">#</a> 4.4 验证数据规则的合法性</h4> <ol><li>在  <code>/router/userinfo.js</code> 模块中，导入验证数据合法性的中间件</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入验证数据合法性的中间件</span>
<span class="token keyword">const</span> expressJoi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@escook/express-joi'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>在 <code>/router/userinfo.js</code> 模块中，导入需要的验证规则对象</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入验证数据合法性的中间件</span>
<span class="token keyword">const</span> expressJoi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@escook/express-joi'</span><span class="token punctuation">)</span>
<span class="token comment">// 导入需要的验证规则对象</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> update_userinfo_schema <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../schema/user'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>在 <code>/router/userinfo.js</code> 模块中，修改  更新用户的基本信息 的路由如下</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>update_userinfo_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updateUserInfo<span class="token punctuation">)</span>

</code></pre></div><ol start="4"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// /router/userinfo.js</span>

<span class="token comment">// 导入 express</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> route <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./user'</span><span class="token punctuation">)</span> 
<span class="token comment">// 导入验证数据合法性的中间件</span>
<span class="token keyword">const</span> expressJoi <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'@escook/express-joi'</span><span class="token punctuation">)</span>
<span class="token comment">// 导入需要的验证规则对象</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> update_userinfo_schema <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../schema/user'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 导入用户信息的处理函数模块</span>
<span class="token keyword">const</span> userinfo_handler <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../router_handler/userinfo'</span><span class="token punctuation">)</span>

<span class="token comment">// 获取用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>getUserInfo<span class="token punctuation">)</span>
<span class="token comment">// 更新用户的基本信息</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/userinfo'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>update_userinfo_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updateUserInfo<span class="token punctuation">)</span>

<span class="token comment">// 向外共享路由对象</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><h4 id="_4-4-实现更新用户基本信息的功能"><a href="#_4-4-实现更新用户基本信息的功能" class="header-anchor">#</a> 4.4 实现更新用户基本信息的功能</h4> <ol><li>定义待执行的 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 定义更新用户信息的 sql 语句</span>
<span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">update ev_users set ? where id=?</span><span class="token template-punctuation string">`</span></span>

</code></pre></div><ol start="2"><li>调用 <code>db.query()</code> 执行 <code>SQL</code> 语句并传参</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 调用 db.query() 执行 sql 语句</span>
db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">[</span>req<span class="token punctuation">.</span>body<span class="token punctuation">,</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>id<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 执行 sql 语句失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

  <span class="token comment">// 执行 sql 语句成功，但影响函数不为 1、</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'修改用户基本信息失败！'</span><span class="token punctuation">)</span>

  <span class="token comment">// 修改用户信息成功</span>
  <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'修改用户基本信息成功！'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户基本信息的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updateUserInfo</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义更新用户信息的 sql 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">update ev_users set ? where id=?</span><span class="token template-punctuation string">`</span></span>

  <span class="token comment">// 调用 db.query() 执行 sql 语句</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">[</span>req<span class="token punctuation">.</span>body<span class="token punctuation">,</span> req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>id<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 sql 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// 执行 sql 语句成功，但影响函数不为 1、</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'修改用户基本信息失败！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 修改用户信息成功</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'修改用户基本信息成功！'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_5-重置密码"><a href="#_5-重置密码" class="header-anchor">#</a> 5. 重置密码</h3> <h4 id="_5-1-实现步骤"><a href="#_5-1-实现步骤" class="header-anchor">#</a> 5.1 实现步骤</h4> <ol><li>定义路由和处理函数</li> <li>验证表单数据</li> <li>实现重置密码的功能</li></ol> <h4 id="_5-2-定义路由和处理函数"><a href="#_5-2-定义路由和处理函数" class="header-anchor">#</a> 5.2 定义路由和处理函数</h4> <ol><li>在 <code>/router/userinfo.js</code> 模块中，新增  重置密码 的路由</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的路由</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/updatepwd'</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updatePassword<span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li><p>在  <code>/router_handler/userinfo.js</code> 模块中，定义并向外共享  重置密码 的路由处理函数</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updatePassword</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div></li></ol> <h4 id="_5-3-验证数据表单"><a href="#_5-3-验证数据表单" class="header-anchor">#</a> 5.3 验证数据表单</h4> <blockquote><p>核心验证思路：旧密码与新密码，必须符合密码的验证规则，并且新密码不能与旧密码一致</p></blockquote> <ol><li>在  <code>/schema/user.js</code> 模块中，使用  <code>exports</code> 向外共享如下的  验证规则对象</li></ol> <ul><li><code>joi.ref('oldPwd')</code> 表示 <code>newPwd</code> 的值必须和 <code>oldPwd</code> 的值保持一致</li> <li><code>joi.not(joi.ref('oldPwd'))</code> 表示 <code>newPwd</code> 的值不能等于 <code>oldPwd</code> 的值</li> <li><code>.concat()</code> 用于合并 <code>joi.not(joi.ref('oldPwd'))</code> 和 <code>password</code> 这两条验证规则</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码验证规则对象</span>
exports<span class="token punctuation">.</span>update_password_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    oldPwd<span class="token operator">:</span> password<span class="token punctuation">,</span>
    newPwd<span class="token operator">:</span> joi<span class="token punctuation">.</span><span class="token function">not</span><span class="token punctuation">(</span>joi<span class="token punctuation">.</span><span class="token function">ref</span><span class="token punctuation">(</span><span class="token string">'oldPwd'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="2"><li>在  <code>/router/userinfo.js</code> 模块中，导入需要的验证规则对象</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入需要的验证规则对象</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> update_userinfo_schema<span class="token punctuation">,</span> update_password_schema <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../schema/user'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>并在  重置密码的路由 中，使用  update_password_schema 规则验证表单的数据</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的路由</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/updatepwd'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>update_password_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updatePassword<span class="token punctuation">)</span>
</code></pre></div><h4 id="_5-4-实现重置密码的功能"><a href="#_5-4-实现重置密码的功能" class="header-anchor">#</a> 5.4  实现重置密码的功能</h4> <ol><li>根据  <code>id</code> 查询用户是否存在</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updatePassword</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 执行根据 id 查询用户数据的 SQL 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where id=?</span><span class="token template-punctuation string">`</span></span>

  <span class="token comment">// 执行 SQL 语句查询用户是否存在</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 SQL 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// 判断结果是否存在</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'用户不存在！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 判断用户输入的旧密码是否正确</span>
    res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_5-5-判断提交的-旧密码-是否正确"><a href="#_5-5-判断提交的-旧密码-是否正确" class="header-anchor">#</a> 5.5 判断提交的 旧密码 是否正确</h4> <ol><li>在头部区域导入 <code>bcryptjs</code></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> bcrypt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcryptjs'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>使用 <code>bcrypt.compareSync(提交的密码，数据库中的密码)</code> 方法验证密码是否正确</li></ol> <ul><li><code>compareSync()</code> 函数的返回值为布尔值，<code>true</code> 表示密码正确，<code>false</code> 表示密码错误</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 判断用户输入的旧密码是否正确</span>
<span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>oldPwd<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'旧密码错误！'</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>完整密码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updatePassword</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 执行根据 id 查询用户数据的 SQL 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where id=?</span><span class="token template-punctuation string">`</span></span>

  <span class="token comment">// 执行 SQL 语句查询用户是否存在</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 SQL 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// 判断结果是否存在</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'用户不存在！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 判断用户输入的旧密码是否正确</span>
    <span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>oldPwd<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'旧密码错误！'</span><span class="token punctuation">)</span>

    res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h4 id="_5-6-实现重置密码的功能"><a href="#_5-6-实现重置密码的功能" class="header-anchor">#</a> 5.6 实现重置密码的功能</h4> <ol><li>定义更新用户密码的 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 定义更新密码的 SQL 语句</span>
<span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">update ev_users set password=? where id=?</span><span class="token template-punctuation string">`</span></span>
</code></pre></div><ol start="2"><li>对新密码进行加密处理</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 对新密码进行加密处理</span>
<span class="token keyword">const</span> newPwd <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>newPwd<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>
</code></pre></div><ol start="3"><li>执行 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 执行 SQL 语句，根据 id 更新用户的密码</span>
db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">[</span>newPwd<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">//语句执行失败</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

  <span class="token comment">// 语句执行成功，但是影响行数不等于 1</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新密码失败！'</span><span class="token punctuation">)</span>
  
  <span class="token comment">// 更新密码成功</span>
  res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新密码成功！'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="4"><li>完整代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 重置密码的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updatePassword</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 执行根据 id 查询用户数据的 SQL 语句</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">select * from ev_users where id=?</span><span class="token template-punctuation string">`</span></span>

  <span class="token comment">// 执行 SQL 语句查询用户是否存在</span>
  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 执行 SQL 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// 判断结果是否存在</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>length <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'用户不存在！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 判断用户输入的旧密码是否正确</span>
    <span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>oldPwd<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'旧密码错误！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 定义更新密码的 SQL 语句</span>
    <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">update ev_users set password=? where id=?</span><span class="token template-punctuation string">`</span></span>

    <span class="token comment">// 对新密码进行加密处理</span>
    <span class="token keyword">const</span> newPwd <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>newPwd<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>
    
    <span class="token comment">// 执行 SQL 语句，根据 id 更新用户的密码</span>
    db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">[</span>newPwd<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token comment">//语句执行失败</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

      <span class="token comment">// 语句执行成功，但是影响行数不等于 1</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新密码失败！'</span><span class="token punctuation">)</span>
      
      <span class="token comment">// 更新密码成功</span>
      res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新密码成功！'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div><h3 id="_6-更换头像"><a href="#_6-更换头像" class="header-anchor">#</a> 6.  更换头像</h3> <h4 id="_6-1-实现步骤"><a href="#_6-1-实现步骤" class="header-anchor">#</a> 6.1 实现步骤</h4> <ol><li>定义路由和处理函数</li> <li>验证表单数据</li> <li>实现更新用户头像的功能</li></ol> <h4 id="_6-2-定义路由和处理函数"><a href="#_6-2-定义路由和处理函数" class="header-anchor">#</a> 6.2 定义路由和处理函数</h4> <ol><li>在 <code>/router/userinfo.js</code> 模块中，新增  更新用户头像 的路由</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户头像的路由</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/update/avatar'</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updateAvatar<span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>在  <code>/router_handler/userinfo.js</code> 模块中，定义并向外共享  更新用户头像 的路由处理函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户头像的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updateAvatar</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
 res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h4 id="_6-3-验证表单数据"><a href="#_6-3-验证表单数据" class="header-anchor">#</a> 6.3 验证表单数据</h4> <ol><li>在 <code>/schema/user.js</code> 验证规则模块中，定义  avatar 的验证规则</li></ol> <ul><li><code>dataUri()</code> 指的是如下格式的字符串数据</li> <li><code></code></li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 验证头像数据</span>
<span class="token keyword">const</span> avatar <span class="token operator">=</span> joi<span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">dataUri</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">required</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 验证规则对象 - 更新头像</span>
exports<span class="token punctuation">.</span>update_avatar_schema <span class="token operator">=</span> <span class="token punctuation">{</span>
  body<span class="token operator">:</span> <span class="token punctuation">{</span>
    avatar
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre></div><ol start="2"><li>并使用 <code>exports</code> 向外共享如下的  验证规则对象</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入需要的验证规则对象</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> update_avatar_schema <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'../schema/user'</span><span class="token punctuation">)</span>

<span class="token comment">// 更新用户头像的路由</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/update/avatar'</span><span class="token punctuation">,</span> <span class="token function">expressJoi</span><span class="token punctuation">(</span>update_avatar_schema<span class="token punctuation">)</span><span class="token punctuation">,</span> userinfo_handler<span class="token punctuation">.</span>updateAvatar<span class="token punctuation">)</span>
</code></pre></div><h4 id="_6-4-实现更新用户头像的操作"><a href="#_6-4-实现更新用户头像的操作" class="header-anchor">#</a> 6.4  实现更新用户头像的操作</h4> <ol><li>定义更新用户头像的 <code>SQL</code> 语句</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token string">'update ev_users set user_pic=? where id=?'</span>
</code></pre></div><ol start="2"><li>调用 <code>db.query()</code> 执行 <code>SQL</code> 语句，更新对应用户的头像</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 更新用户头像的处理函数</span>
exports<span class="token punctuation">.</span><span class="token function-variable function">updateAvatar</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 更新用户头像的 sql 字段</span>
  <span class="token keyword">const</span> sql <span class="token operator">=</span> <span class="token string">'update ev_users set user_pic=? where id=?'</span>

  db<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span>sql<span class="token punctuation">,</span> <span class="token punctuation">[</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>avatar<span class="token punctuation">,</span> req<span class="token punctuation">.</span>user<span class="token punctuation">.</span>id<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> results</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// SQL 语句失败</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>

    <span class="token comment">// SQL 语句成功，但是影响行数不等于 1</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>results<span class="token punctuation">.</span>affectedRows <span class="token operator">!==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新头像失败！'</span><span class="token punctuation">)</span>

    <span class="token comment">// 更新用户头像成功</span>
    <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'更新头像成功！'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

</code></pre></div></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/heima2020/node/day06.html" class="prev">
        Node 第 6 天
      </a></span> <span class="next"><a href="/heima2020/node/day08.html">
        Node 第 8 天
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----></div></div>
    <script src="/heima2020/assets/js/app.e2adc9d2.js" defer></script><script src="/heima2020/assets/js/2.7389c9d3.js" defer></script><script src="/heima2020/assets/js/40.a6ba2743.js" defer></script>
  </body>
</html>
